unit Packet;

interface

uses
  Classes, SyncObjs;


type
  TPacket = class
  private
  public
    Data : pointer;
    Size : int64;
    option: integer;
    constructor Create(AData:pointer; ASize:int64); overload;
    Constructor Create(AData:Pointer; ASize:int64; AOption:integer); overload;
    destructor Destroy; override;
  end;

  TPacketList = Class
    private
      FList: TList;
      FCS: TCriticalSection;
    public
      function Add(Data:pointer; Size:int64; option:integer):TPacket; overload;
      function Add(Data:pointer; Size:int64):TPacket; overload;
      
      function Get(var Data:pointer; var Size:int64):Boolean; overload;
      function Get(Var Data:pointer; var Size:int64; var Command:integer):Boolean; overload;
      procedure Clear;

      Constructor Create;
      Destructor  Destroy; override;

  End;


implementation

{ TPacket }

constructor TPacket.Create(AData: pointer; ASize: int64);
begin
  inherited Create;

  Size := ASize;
  if Size > 0 then begin
    GetMem(Data, Size);
    Move(AData^, Data^, Size);
  end else
    Data := nil;
end;

constructor TPacket.Create(AData: Pointer; ASize: int64; AOption: integer);
begin
  inherited Create;
  Size := ASize;
  if Size > 0 then begin
    GetMem(Data, Size);
    Move(AData^, Data^, Size);
  end else
    Data := nil;

  option := AOption;
end;

destructor TPacket.Destroy;
begin
  if Data <> nil then FreeMem(Data);

  inherited;
end;

{ TPacketList }

constructor TPacketList.Create;
begin
  FList := TList.Create;
  FCS := TCriticalSection.Create;
end;

destructor TPacketList.Destroy;
begin
  self.Clear;
  
  FList.Free;
  FCS.Free;
  inherited;
end;


function  TPacketList.Add(Data: pointer; Size: int64):TPacket;
var
  Packet : TPacket;
begin
  FCS.Enter;
  try
    Packet := TPacket.Create(Data, Size);
    Result := Packet;
    FList.Add(Packet);
  finally
    FCS.Leave;
  end;
end;

function TPacketList.Get(var Data: pointer; var Size: int64;
  var Command: integer): Boolean;
var
  Packet : TPacket;
begin
  FCS.Enter;
  try
    Data := nil;
    Size := 0;
    Result := false;

    if FList.Count = 0 then Exit;

    Result := true;
    Packet := Pointer(FList[0]);
    FList.Delete(0);
    try
      Size := Packet.Size;
      if Size > 0 then begin
        GetMem(Data, Size);
        Move(Packet.Data^, Data^, Size);
      end;
      Command := Packet.option;
    finally
      Packet.Free;
    end;
  finally
    FCS.Leave;
  end;

end;


function TPacketList.Get(var Data: pointer; var Size: int64): Boolean;
var
  Packet : TPacket;
begin
  FCS.Enter;
  try
    Data := nil;
    Size := 0;
    Result := false;

    if FList.Count = 0 then Exit;

    Result := true;
    Packet := Pointer(FList[0]);
    FList.Delete(0);
    try
      Size := Packet.Size;
      if Size > 0 then begin
        GetMem(Data, Size);
        Move(Packet.Data^, Data^, Size);
      end;
    finally
      Packet.Free;
    end;
  finally
    FCS.Leave;
  end;
end;

function TPacketList.Add(Data: pointer; Size: int64; option: integer): TPacket;
begin
  Result := Self.Add(Data, Size);
  Result.option := option;
end;

procedure TPacketList.Clear;
var
  Packet: TPacket;
  I: Integer;
begin
  FCS.Enter;
  try
    for I := FList.Count - 1 downto 0 do
      TPacket(FList.Items[i]).Free;
      
    FList.Clear;

  finally
    FCS.Leave;
  end;
end;


end.
